import 'dart:async';

import 'package:casdon/common/service/service_manager.dart';
import 'package:casdon/common/service/tuya_service.dart';
import 'package:casdon/core/logger/log.dart';
import 'package:casdon/modules/home/application/notification/tuya_auth_notifier.dart';
import 'package:casdon/modules/home/data/model/unified_device_model.dart';
import 'package:casdon/modules/home/domain/states/unified_device_list_state.dart';
import 'package:casdon/modules/home/domain/usecase/ciot_device_list_usecase.dart';
import 'package:casdon/modules/home/providers/home_provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class DiviceListNotifier extends AsyncNotifier<UnifiedDeviceListState> {
  TuyaService get _tuyaService => ServiceManager().getService<TuyaService>();
  CiotDeviceListUsecase get _useCase => ref.read(ciotDeviceListUsecaseProvider);

  /// 清空当前状态
  void clear() {
    state = AsyncValue.data(UnifiedDeviceListState.initial());
  }

  @override
  Future<UnifiedDeviceListState> build() async {
    final isLoggedIn = ref.read(tuyaLoginStateProvider);
    if (!isLoggedIn) {
      await ref.read(tuyaLoginProvider.notifier).login();
    }
    TuyaService().onHomeInfoUpdated(_handleHomeInfoUpdate);
    return _fetchData(showLoading: false);
  }

  Future<void> refresh() async {
    try {
      final isLoggedIn = ref.read(tuyaLoginStateProvider);
      if (!isLoggedIn) {
        await ref.read(tuyaLoginProvider.notifier).login();
      }

      final currentState = state.valueOrNull;
      final showLoading = currentState?.data.isEmpty ?? true;
      if (showLoading) {
        // state = const AsyncValue.loading();
      }
      final newState = await _fetchData(showLoading: false);
      state = AsyncValue.data(newState);
    } catch (e, st) {
      Log.e("首页刷新用户设备列表失败", e, st);
      // state = AsyncValue.error(e, st);
      if (state.hasError && state.valueOrNull?.data.isNotEmpty == true) {
        state = AsyncValue.data(state.valueOrNull!);
      }
    }
  }

  Future<UnifiedDeviceListState> _fetchData({bool showLoading = true}) async {
    try {
      if (showLoading) {
        // state = const AsyncValue.loading();
      }

      final results = await Future.wait([
        _safeTuyaDeviceList(),
        _safeCiotDeviceList(),
      ]);

      return _mergeDeviceResults(results);
    } catch (e, stack) {
      Log.e("获取设备列表失败", e, stack);
      rethrow;
    }
  }

  Future<List<UnifiedDeviceModel>> _safeTuyaDeviceList() async {
    try {
      if (!ref.read(tuyaLoginStateProvider)) {
        return []; // 未登录时返回空
      }

      final devices = await _tuyaService.homeDeviceList();

      Log.w("获取到涂鸦设备：${devices.length} 台");
      for (final d in devices) {
        Log.w("涂鸦设备 devId=${d.devId}, name=${d.name}");
        TuyaService().onDeviceInfoUpdated(d.devId!, _onDeviceInfoChanged);
      }
      return devices
          .map<UnifiedDeviceModel>((e) => UnifiedDeviceModel.fromTuya(e))
          .toList();
    } catch (e) {
      Log.w("涂鸦设备列表获取失败");
      return [];
    }
  }

  Future<List<UnifiedDeviceModel>> _safeCiotDeviceList() async {
    try {
      final devices = await _useCase.execute();
      if (devices == null) {
        return [];
      }
      return devices
          .map<UnifiedDeviceModel>((e) => UnifiedDeviceModel.fromApi(e))
          .toList();
    } catch (e) {
      Log.w("CIOT设备列表获取失败");
      return [];
    }
  }

  UnifiedDeviceListState _mergeDeviceResults(
    List<List<UnifiedDeviceModel>> results,
  ) {
    final allDevices = [...results[0], ...results[1]];

    if (allDevices.isEmpty && results.every((list) => list.isEmpty)) {
      return UnifiedDeviceListState.initial();
    }

    return UnifiedDeviceListState(data: allDevices);
  }

  void _handleHomeInfoUpdate(dynamic event) {
    if (event == null) {
      Log.w("收到空的 Home 事件");
      return;
    }

    if (event is! Map) {
      Log.w("Home 事件格式异常: $event");
      return;
    }

    final data = Map<String, dynamic>.from(event as Map);
    final type = data['type']?.toString() ?? '';
    Log.d("Home 事件 type=$type");

    switch (type) {
      case "deviceAdded":
        // 新设备加入，拉取最新列表
        _onDeviceAdded(event);
        break;
      case "sharedInfoUpdate":
        _scheduleRefresh();
      default:
        Log.w("未处理的 Home 事件类型: $type");
    }
  }

  void _scheduleRefresh() {
    Timer(const Duration(microseconds: 1500), () async {
      await refresh();
    });
  }

  void _onDeviceInfoChanged(dynamic event) {
    if (event == null) {
      Log.w("收到空的设备信息事件");
      return;
    }

    if (event is! Map) {
      Log.w("设备信息事件格式异常: $event");
      return;
    }

    final data = Map<String, dynamic>.from(event as Map);
    final type = data['type']?.toString() ?? '';
    final deviceId = data['deviceId']?.toString();

    Log.d("设备信息事件 type=$type, deviceId=$deviceId");

    switch (type) {
      case "infoUpdate":
        final model = data['model'];
        _applyDeviceInfoUpdate(deviceId, model);
        break;
      case "removed":
        _applyDeviceRemoved(deviceId);
        break;
      default:
        Log.w("未处理的设备信息事件类型: $type");
    }
  }

  // 设备更新事件
  void _applyDeviceInfoUpdate(String? deviceId, dynamic model) {
    if (deviceId == null || model is! Map) {
      Log.w("无法更新设备，deviceId 或 model 无效");
      return;
    }

    final current = state.valueOrNull;
    if (current == null || current.data.isEmpty) {
      // 当前没有缓存设备列表，直接拉取最新数据
      _scheduleRefresh();
      return;
    }

    final modelMap = Map<String, dynamic>.from(model);
    final updatedList = current.data.map((device) {
      if (device.devId != deviceId) return device;

      final isOnline = modelMap['isOnline'];
      return UnifiedDeviceModel(
        pid: modelMap['productId']?.toString() ?? device.pid,
        devId: device.devId,
        name: modelMap['name']?.toString() ?? device.name,
        icon: modelMap['iconUrl']?.toString() ?? device.icon,
        isOnline: isOnline is bool ? isOnline : device.isOnline,
        uuid: modelMap['uuid']?.toString() ?? device.uuid,
        source: device.source,
        rawData: model,
      );
    }).toList();

    state = AsyncValue.data(current.copyWith(data: updatedList));
  }

  void _applyDeviceRemoved(String? deviceId) {
    if (deviceId == null) {
      Log.w("设备移除事件缺少 deviceId");
      return;
    }

    final current = state.valueOrNull;
    if (current == null || current.data.isEmpty) {
      _scheduleRefresh();
      return;
    }

    final filtered = current.data.where((d) => d.devId != deviceId).toList();

    if (filtered.length == current.data.length) {
      // 没有命中则触发一次刷新，避免本地数据不同步
      Log.w("设备移除事件未命中本地列表 deviceId=$deviceId，尝试刷新");
      _scheduleRefresh();
      return;
    }

    state = AsyncValue.data(current.copyWith(data: filtered));
    Log.d("设备已移除并更新列表 deviceId=$deviceId");
  }

  void _onDeviceAdded(dynamic event) {
    if (event == null || event is! Map) {
      Log.w("设备新增事件格式异常: $event");
      _scheduleRefresh();
      return;
    }

    final data = Map<String, dynamic>.from(event as Map);
    final model = data['deviceModel'] ?? data['model'];
    if (model is! Map) {
      Log.w("设备新增事件缺少 deviceModel: $event");
      _scheduleRefresh();
      return;
    }

    final modelMap = Map<String, dynamic>.from(model);
    final devId = modelMap['devId']?.toString();
    if (devId == null) {
      Log.w("设备新增事件缺少 devId: $event");
      _scheduleRefresh();
      return;
    }

    final current = state.valueOrNull ?? UnifiedDeviceListState.initial();
    final alreadyExists = current.data.any((device) => device.devId == devId);
    if (alreadyExists) {
      Log.d("设备已存在，跳过重复添加 devId=$devId");
      return;
    }

    final isOnline = modelMap['isOnline'];
    final newDevice = UnifiedDeviceModel(
      pid: modelMap['productId']?.toString() ?? '',
      devId: devId,
      name: modelMap['name']?.toString() ?? '',
      icon: modelMap['iconUrl']?.toString(),
      isOnline: isOnline is bool ? isOnline : false,
      uuid: modelMap['uuid']?.toString(),
      source: DeviceSource.tuya,
      rawData: model,
    );

    state = AsyncValue.data(
      current.copyWith(data: [...current.data, newDevice]),
    );
    Log.d("设备新增并已加入列表 devId=$devId");
  }
}
